package core;

import static org.junit.Assert.*;

import java.util.Calendar;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import persistence.DataPersistor;

import core.exception.IllegalAddException;
import core.exception.IllegalEditException;
import core.exception.IllegalRemoveException;
import core.exception.NotFoundException;
import core.exception.SaveException;

public class ItemFacadeTest {
	
	static ItemFacade iFacade;
	static ContainerFacade cFacade;
	static ProductFacade pFacade;
	static Container testSU;
	static Container testG1;
	static Container testG2;
	static Product testP;
	static Item testI1;
	static Item testI2;

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		testP = new Product(new Barcode("512345123459", BarcodeType.PRODUCT),
				"A test Product.",
				new Amount(3.59F, UnitOfMeasurement.kilograms),
				6, 9);
		DataPersistor.instance().init("-serial");
		ItemFacade.clearAllData();
		ContainerFacade.clearAllData();
		ProductFacade.clearAllData();
	}

	@AfterClass
	public static void tearDownAfterClass() throws Exception {
		testP = null;
	}

	@Before
	public void setUp() throws Exception {
		iFacade = ItemFacade.instance();
		pFacade = ProductFacade.instance();
		cFacade = ContainerFacade.instance();
		cFacade.addStorageUnit("TestSU");
		testSU = cFacade.get_rootUnit().lookupContainer("TestSU");
		testSU.addContainer("TestG1");
		testG1 = testSU.lookupContainer("TestG1");
		testSU.addContainer("TestG2");
		testG2 = testSU.lookupContainer("TestG2");
		pFacade.createProduct(testP, testSU);
		testI1 = null;
		try {
			testI1 = iFacade.addItem(testP, testSU);
		} catch (IllegalAddException e) {
			e.printStackTrace();
			fail("IllegalAddException");
		}
	}

	@After
	public void tearDown() throws Exception {
		ItemManager.setInstance(null);
		ProductManager.setInstance(null);
		RootStorageUnit.setInstance(null);
		ItemFacade.setInstance(null);
		ProductFacade.setInstance(null);
		ContainerFacade.setInstance(null);
	}

	@Test
	public void testCanAddItem() {
		
		assertFalse(iFacade.canAddItem(testI1, testSU));
		assertTrue(iFacade.canAddItem(testI1, testG2));
	}

	@Test
	public void testAddItem() {
		assertTrue(testI1 != null);
		assertTrue(testSU.containsItem(testI1));
		assertFalse(testG2.containsItem(testI1));
	
	}

	@Test
	public void testCanRemoveItem() {
		Item testI1 = null;
		try {
			testI1 = iFacade.addItem(testP, testG1);
		} catch (IllegalAddException e) {
			e.printStackTrace();
			fail("IllegalAddException");
		} catch (SaveException e){
			e.printStackTrace();
			fail("SaveException");
		}
		
		assertTrue(iFacade.canRemoveItem(testI1));
	}

	@Test
	public void testRemoveItem() {
		assertTrue(testSU.containsItem(testI1));
		
		try {
			iFacade.removeItem(testI1);
		} catch (IllegalRemoveException e) {
			e.printStackTrace();
			fail("IllegalRemoveException");
		} catch (NotFoundException e) {
			e.printStackTrace();
			fail("NotFoundException");
		} catch (SaveException e){
			e.printStackTrace();
			fail("SaveException");
		}
		
		assertTrue(testI1.isUsed());
	}

	@Test
	public void testCanMoveItem() {
		assertTrue(iFacade.canMoveItem(testI1, testSU, testG2));
		assertFalse(iFacade.canMoveItem(testI1, testG2, testG1));

	}

	@Test
	public void testMoveItem() {
		assertTrue(testSU.containsItem(testI1));
		assertFalse(testG2.containsItem(testI1));
		
		try {
			iFacade.moveItem(testI1, testG1, testG2);
		} catch (IllegalAddException e) {
			e.printStackTrace();
			fail("IllegalAddException");
		} catch (NotFoundException e) {
			e.printStackTrace();
			fail("NotFoundException");
		}
		
		assertFalse(testSU.containsItem(testI1));
		assertTrue(testG2.containsItem(testI1));
		
	}
	

	@Test
	public void testCanEditItem() {
		assertTrue(iFacade.canEditItem(testI1, "01/14/2012"));
		assertFalse(iFacade.canEditItem(testI1, "garbage"));
	}

	@Test
	public void testEditItem() {
		
		try {
			iFacade.editItem(testI1, "01/14/2012");
		} catch (IllegalEditException e) {
			e.printStackTrace();
			fail("IllegalEditException");
		} catch (NotFoundException e) {
			e.printStackTrace();
			fail("NotFoundException");
		} catch (SaveException e){
			e.printStackTrace();
			fail("SaveException");
		}
		
		assertEquals(testI1.getEntryDate().get(Calendar.YEAR), 2012);
	}

}
